
#include <xercesc/dom/DOM.hpp>
#include <xercesc/framework/LocalFileInputSource.hpp>
#include <xercesc/parsers/XercesDOMParser.hpp>

#include <iostream>

#include "XMLLoading.h"

XERCES_CPP_NAMESPACE_USE 

XMLLoading::XMLLoading()
{
    //empty constructor
}

XMLLoading::~XMLLoading()
{
    //empty destructor
}

void XMLLoading::XMLLoad(
            std::vector<hash_map<string, string, hash<string>, eqstr> >&destination,
            string url )
{
  bool bFailed = false;
  
  if(!destination.empty()){
  	destination.clear();
  }
  hash_map<string, string, hash<string>, eqstr> temp; 
  destination.push_back(temp);//this is needed,
                              //because the first hash_map NEEDS 
                              //to be the global hash_map
  try 
  {
    XMLPlatformUtils::Initialize();
    XercesDOMParser parser;
    CustomErrorHandler handler;
    
    parser.setErrorHandler(&handler);
    parser.setValidationScheme(XercesDOMParser::Val_Auto);
    parser.setDoNamespaces(false);
    parser.setDoSchema(false);
    parser.setCreateEntityReferenceNodes(false);
    
    XMLCh* src = XMLString::transcode(url.c_str());
    LocalFileInputSource source(src);

    parser.parse(source);
    
    bFailed = (parser.getErrorCount() != 0);
    
    if (bFailed)
    {
      std::cerr << "Your configuration file is '" << url;
      std::cerr << "'" << std::endl;
      exit(1);
    }
    else
    {
        DOMDocument *pDoc = parser.getDocument();

        DOMNode *pN1 = pDoc->getFirstChild();   //<xpr/>

        DOMNode *pN2a = pN1->getFirstChild();   //"text" in <xpr/>
        DOMNode *pN2b = pN2a->getNextSibling(); //<thread/> or <global/>

        while(pN2b != NULL) //vector filling with hash_map's
        {
            hash_map<string, string, hash<string>, eqstr> tags;
            
            DOMNode *pN3a = pN2b->getFirstChild(); //"text" in <thread/> or <global/>
            DOMNode *pN3b = pN3a->getNextSibling();//<user/>, <pass/>, ...
            
            while(pN3b != NULL) //hash_map filling
            {
                /*
                std::cout<< XMLString::transcode(pN3b->getNodeName())<< std::endl;
                std::cout<< XMLString::transcode(pN3b->getTextContent())<< std::endl;
                //*/
                char* cTemp1 = XMLString::transcode(pN3b->getNodeName());
                char* cTemp2 = XMLString::transcode(pN3b->getTextContent());
                
                tags[string(cTemp1)]
                        = string(string(cTemp2));
                
                pN3a = pN3b->getNextSibling();  //"text" between <user/>, <pass/>, ...
                pN3b = pN3a->getNextSibling();  //<user/>, <pass/>, ...
            }
            
            string temp = XMLString::transcode(pN2b->getNodeName());
                        
            if("global" == temp)
            {    
                destination[0]=tags;
            }
            if("thread" == temp)
            {
                destination.push_back(tags);
            }
            pN2a = pN2b->getNextSibling();  //"text" between <thread/> or <global/>
            pN2b = pN2a->getNextSibling();  //<thread/> or <global/>
        }
    } 
  }
  catch(...)
  {
    std::cerr<<"There was an exception while processing file: '" << url << "'" <<std::endl;
  }

  XMLPlatformUtils::Terminate();
  // Other terminations and cleanup.
}

void XMLLoading::displayAll(
        std::vector<hash_map<string, string, hash<string>, eqstr> >&destination,
        string url)
{       //for displaying the full content of the vector and its hash_map's
    
    hash_map<string, string, hash<string>, eqstr> temp_h;

    hash_map<string, string, hash<string>, eqstr>::iterator iterator;

    for(uint i =0;i!=destination.size();i++)
    {
        std::cout << "hash_map number= " << i << std::endl;
        temp_h = destination.at(i);
        
        iterator = temp_h.begin();
        if (0 == i)
        {
            std::cout << "Global has the following tree-structure:" << std::endl;
        }
        else
        {
            std::cout << "Thread " << i -1  << " has the following tree-structure:" << std::endl;
        }
        while( iterator != temp_h.end() ) {
            std::cout << "<"<< iterator->first << "> '";
            std::cout << iterator->second;
            std::cout << "' </"<< iterator->first << ">" << std::endl;
            iterator++;
        }
    }
}

void CustomErrorHandler::warning(const SAXParseException& e )
{
    displayError(e);
}

void CustomErrorHandler::error(const SAXParseException& e )
{
    displayError(e);
}

void CustomErrorHandler::fatalError(const SAXParseException& e )
{
    displayError(e);
}

void CustomErrorHandler::resetErrors()
{
    //std::cerr<<"resetErros"<<std::endl;
}

void CustomErrorHandler::displayError(const SAXParseException& e )
{
    std::cerr<<"There has been a typo in your configuration file on line: ";
    std::cerr<<e.getLineNumber()<<std::endl;
}
